package analiseSintatica.Regras.Expressoes;

import analiseSintatica.Regras.*;
import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSemantica.ErroSemantico;
import analiseSemantica.Tipos.TipoSemantico;
import analiseSemantica.Tipos.TiposSemanticos;
import analiseSemantica.estruturadedados.Identificador;
import analiseSintatica.AnalisadorSintatico;
import analiseSintatica.ErroSintaticoException;
import java.util.LinkedList;

/**
 *
 * @author linton
 * @author nathy
 */
public class RegraAtribuicao extends Regra{

    protected static Regra instancia;
    protected String estrutura = "<variavel> '=' <expressao>";

    /**
     * Construtor privado necessario ao singleton
     */
    private RegraAtribuicao() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraAtribuicao getInstance() {
        if (instancia == null) {
            instancia = new RegraAtribuicao();
        }
        return (RegraAtribuicao) instancia;
    }

    @Override
    public TiposSemanticos analisar(LinkedList<LinkToken> tokens) throws ErroSintaticoException {

	    LinkToken identificador = tokens.getFirst();
	
	    TiposSemanticos atribuicao = RegraElementoVar.getInstance().analisar(tokens);
	    reconheceToken(tokens, "=", estrutura);
//	    LinkToken token2 = tokens.getFirst();
	    TiposSemanticos atribuicao2 = RegraExpressao.getInstance().analisar(tokens);
	    
	    //ANALISE SEMANTICA
	    if(atribuicao != null && atribuicao2 != null){
	    	TipoSemantico tipoVariavel = atribuicao.getFirst();
	        String nome = (String) tipoVariavel.getNomeTipo();
	        
	        TipoSemantico tipoExpressao = atribuicao2.getFirst();
	
	        Identificador id = (Identificador)AnalisadorSintatico.escopoatual.find(identificador.getLexema());
	        if(id.isConstante()){
	        	AnalisadorSintatico.errosemanticos.add(new ErroSemantico("Constate "+id.getLexema()+" nao pode sofrer uma atribuicao", identificador.getLinha()));
	        	atribuicao = null;
	        }else if(id.isPonteiro() && !corresponde(id.getTipo(), (String)tipoExpressao.getTipo())){
	        	AnalisadorSintatico.errosemanticos.add(new ErroSemantico("Ponteiro"+id.getLexema()+" nao incompativel com "+(String)tipoExpressao.getTipo(), identificador.getLinha()));
	        	atribuicao = null;
	        }else if(!nome.equals((String)tipoExpressao.getNomeTipo())){
	        	AnalisadorSintatico.errosemanticos.add(new ErroSemantico("Tipo"+nome+" incompativel com "+(String)tipoExpressao.getTipo(), identificador.getLinha()));
	        	atribuicao = null;
	        }
	    }
	    if(atribuicao2 == null){
	    	return null;
	    }
        return atribuicao;
    }

    public static boolean corresponde(String tipoponteiro, String valor){
			if(tipoponteiro.equals(isEndereco(valor)))
				return true;
			else
				return false;
    }
    
    protected void setPrimeiro() {
        this.primeiro = RegraElementoVar.getInstance().getPrimeiro();
    }
}
